package com.cyh.blog.core.shiro.credentials;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.cyh.blog.business.constant.SessionConstant;
import com.cyh.blog.business.service.SysUserService;
import com.cyh.blog.persistence.beans.SysUser;
import com.cyh.blog.util.MD5Util;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import java.util.concurrent.TimeUnit;

public class CredentialsMatch extends SimpleCredentialsMatcher {

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private RedisTemplate redisTemplate;

    private static final  String LOGIN_COUNT_NAME = "login_count_name_";

    private static final  String LOGIN_IS_LOCK = "LOGIN_IS_LOCK_";

    private static final  Integer MAX_COUNT = 5;


    

    /**
     * 将用户密码加密和数据库对比, redis记录用户登录次数
     * @param token
     * @param info
     * @return
     */
    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {

        UsernamePasswordToken utoken = (UsernamePasswordToken) token;
        //得到从reaml存入的用户信息(第一个参数principal)
        Integer id = (Integer) info.getPrincipals().getPrimaryPrincipal();
        SysUser sysUser = sysUserService.selectOne(new EntityWrapper<SysUser>().eq("id",id));
        String username = sysUser.getUsername();
        String loginCountNameKey = LOGIN_COUNT_NAME + username;
        String loginIsLockKey = LOGIN_IS_LOCK + username;

        ValueOperations<String, String> ops = redisTemplate.opsForValue();
        ops.increment(loginCountNameKey, 1);

        Integer count = Integer.parseInt(String.valueOf(ops.get(loginCountNameKey)));
        //超过最大次数
        if (count >= MAX_COUNT){
            ops.set(loginIsLockKey, "LOCK");
            redisTemplate.expire(loginCountNameKey,1, TimeUnit.HOURS);
            redisTemplate.expire(loginIsLockKey,1, TimeUnit.HOURS);
            throw new ExcessiveAttemptsException("由于密码输入错误次数过多，帐号[" + username + "]已被禁止登录！");
        }

        //....将用户密码加密和数据库对比,加密方法
        String s = new String(utoken.getPassword());
        System.out.println(MD5Util.MD5(s,utoken.getUsername()));
        boolean match = this.equals(MD5Util.MD5(s,utoken.getUsername()), sysUser.getPassword());
        if (!match){
            String msg = "您还剩" + (MAX_COUNT - count) + "次重试的机会";
            throw new AccountException("帐号或密码不正确！"+msg);
        }
        redisTemplate.delete(loginIsLockKey);
        redisTemplate.delete(loginCountNameKey);
        //登录成功
        SecurityUtils.getSubject().getSession().setAttribute(SessionConstant.USER_SESSION_KEY,sysUser);
        return true;
    }
}